package medusa

import (
    "log"
    "math"
    "sync"
    "sync/atomic"
)

type event struct {
    code int64
    args []interface{}
}

type EventPump struct {
    name              string
    event_queue_count int64

    chan_event    chan *event
    chan_join     chan int
    ev_code_index int64

    handler_mutex sync.Mutex

    handler map[int64]func(args ...interface{})
}

func NewEventPump(name string) *EventPump {
    evp := new(EventPump)
    evp.Constructor(name)
    return evp
}

/*
func (self *EventPump) Send(evp interface{}, args ...interface{}) {

}

func (self *EventPump) Recv() (evp interface{}, args []interface{}) {

}
*/
func (self *EventPump) Constructor(name string) {
    self.name = name
    self.event_queue_count = 0

    self.chan_event = make(chan *event, math.MaxInt32)
    self.chan_join = make(chan int, 10)
    self.ev_code_index = 0

    self.handler = make(map[int64]func(args ...interface{}))

    go func() {
        log.Printf("[" + self.name + "] evp work")
        for {
            ev := <-self.chan_event
            if ev == nil {
                break //exit signal
            }
            callback := self.handler[ev.code]
            if callback != nil {
                callback(ev.args...)
                atomic.AddInt64(&self.event_queue_count, -1)
            }
        }
        self.chan_join <- 0
        log.Printf("[" + self.name + "] evp free!\n")
    }()
}

func (self *EventPump) AddEventListener(proc func(args ...interface{})) int64 {
    var ev_code int64 = 0

    self.handler_mutex.Lock()
    self.ev_code_index = self.ev_code_index + 1
    ev_code = self.ev_code_index
    self.handler[ev_code] = proc
    self.handler_mutex.Unlock()

    return ev_code
}

func (self *EventPump) DispatchEvent(ev_code int64, args ...interface{}) {

    self.chan_event <- &(event{ev_code, args})
    ev_count := atomic.AddInt64(&self.event_queue_count, 1)

    if ev_count >= 200 {
        log.Printf("["+self.name+"] evp event_count:%v!", ev_count)
    }
}

func (self *EventPump) Join() {
    _ = <-self.chan_join
}

func (self *EventPump) Close() {
    self.chan_event <- nil
}
